-------------------------------------------------------------------------------------
-- JSLExport.ms
-- This utility exports geometry from Max 10 into the JavaScript Literal.
-------------------------------------------------------------------------------------

utility JSLExport "Export JSLiteral 1.0 (.jsl)"
(
	local version = "1.0"
	
	local ostream = undefined
	
	group "Export"
	(
		checkbox cbExportSelOnly		"Selection Only"
		checkbox cbExportTexCoords		"Texture Coords"	checked:true
		checkbox cbExportNormals		"Normals"			checked:true
		checkbox cbExportMaterials		"Materials"			checked:true
		checkbox cbExportAnimation		"Animation"			checked:true
	)
	button btnExport "Save As..." width:80

	function exportMesh meshObj =
	(		
		format "\t\tmesh: {\n" to:ostream
		
		tmesh = snapshotAsMesh meshObj
		vertices = #()
		normals = #()
		texCoords = #()
		
		if tmesh.numFaces > 0 then
		(
			format "\t\t\tindexes: [\n" to:ostream
			for i = 1 to tmesh.numFaces do
			(
				tri = GetFace tmesh i
				pos0 = (i - 1) * 3 + 1
				pos1 = pos0 + 1
				pos2 = pos0 + 2
				
				format "\t\t\t\t%, %, %,\n" (pos0 as integer -1) (pos1 as integer -1) (pos2 as integer -1) to:ostream
				
				vertices[pos0] = GetVert tmesh tri.x
				vertices[pos1] = GetVert tmesh tri.y
				vertices[pos2] = GetVert tmesh tri.z
				
				if cbExportNormals.checked and tmesh.numTVerts > 0 then
				(
					sg = getFaceSmoothGroup tmesh i
					if sg != 0 then
					(
						tnorm = meshop.getFaceRNormals tmesh i
						normals[pos0] = tnorm[1]
						normals[pos1] = tnorm[2]
						normals[pos2] = tnorm[3]
					)
					else
					(
						tnorm = getFaceNormal tmesh i
						normals[pos0] = tnorm
						normals[pos1] = tnorm
						normals[pos2] = tnorm
					)
				)
				
				if cbExportTexCoords.checked and tmesh.numTVerts > 0 then
				(
					tvert = GetTVFace tmesh i
					texCoords[pos0] = GetTVert tmesh tvert.x
					texCoords[pos1] = GetTVert tmesh tvert.y
					texCoords[pos2] = GetTVert tmesh tvert.z
				)
			)
			format "\t\t\t],\n" to:ostream
		)
		
		if vertices.count > 0 then
		(
			format "\t\t\tvertexes: [\n" to:ostream
			for i = 1 to vertices.count do
			(
				vert = vertices[i]
				format "\t\t\t\t%, %, %,\n" vert.x vert.y vert.z to:ostream
			)
			format "\t\t\t],\n" to:ostream
		)
		
		if cbExportTexCoords.checked and texCoords.count > 0 then
		(
			format "\t\t\ttexCoords: [\n" to:ostream
			for i = 1 to texCoords.count do
			(
				uvw = texCoords[i]
				format "\t\t\t\t%, %,\n" uvw.x uvw.y to:ostream
			)
			format "\t\t\t],\n" to:ostream
		)
		
		if cbExportNormals.checked and normals.count > 0 then
		(
			format "\t\t\tnormals: [\n" to:ostream
			for i = 1 to normals.count do
			(
				norm = normals[i]
				format "\t\t\t\t%, %, %,\n" norm.x norm.y norm.z to:ostream
			)
			format "\t\t\t],\n" to:ostream
		)
		
		format "\t\t},\n\n" to:ostream

		return true
	)

	function exportNode node parentName =
	(
		if node == undefined then
			return false
		
		local result = true
		
		format "\t{\n" to:ostream
		format "\t\tname: \"%\",\n" node.name to:ostream
		if parentName != "" then
			format "\t\tparent: \"%\",\n" node.parent.name to:ostream
		if cbExportMaterials.checked and node.material != undefined then
			format "\t\tmaterial: \"%\",\n" node.material.name to:ostream
		
		format "\n" to:ostream
		format "\t\tview: [\n" to:ostream
		for i = 1 to 3 do
			format "\t\t\t%, %, %, %,\n" node.transform[1][i] node.transform[2][i] node.transform[3][i] node.transform[4][i] to:ostream
		format "\t\t\t0.0, 0.0, 0.0, 1.0\n" to:ostream
		format "\t\t],\n\n" to:ostream
		
		if SuperClassOf node == GeometryClass then
			exportMesh node
		
		if cbExportAnimation.checked then
		(
			format "\t\tanimation: {\n"to:ostream
			format "\t\t\tstart: %,\n" (animationRange.start as integer) to:ostream
			format "\t\t\tend: %,\n" (animationRange.end as integer) to:ostream
			
			if node.pos.isAnimated and node.pos.controller != undefined and node.pos.controller.keys.count > 0 then
			(
				format "\t\t\tposition: [\n" to:ostream
				for i = 1 to node.pos.controller.keys.count do
				(
					t = node.pos.controller.keys[i].time
					pos = at time t node.pos
					format "\t\t\t\t{time: %, vec3: [%, %, %]},\n" (t as integer) pos.x pos.y pos.z to:ostream
				)
				format "\t\t\t],\n" to:ostream
			)
			if node.rotation.isAnimated and node.rotation.controller != undefined and node.rotation.controller.keys.count > 0 then
			(
				format "\t\t\trotation: [\n" to:ostream
				for i = 1 to node.rotation.controller.keys.count do
				(
					t = node.rotation.controller.keys[i].time
					rot = at time t node.rotation
					format "\t\t\t\t{time: %, quat: [%, %, %, %]},\n" (t as integer) rot.x rot.y rot.z rot.w to:ostream
				)
				format "\t\t\t],\n" to:ostream
			)
			if node.scale.isAnimated and node.scale.controller != undefined and node.scale.controller.keys.count > 0 then
			(
				format "\t\t\tscale: [\n" to:ostream
				for i = 1 to node.scale.controller.keys.count do
				(
					t = node.scale.controller.keys[i].time
					sca = at time t node.scale
					format "\t\t\t\t{time: %, vec3: [%, %, %]},\n" (t as integer) sca.x sca.y sca.z to:ostream
				)
				format "\t\t\t],\n" to:ostream
			)
			format "\t\t},\n\n"to:ostream
		)

		format "\t},\n" to:ostream
		
		return result
	)

	function exportNodeRecursive node parentName =
	(
		if (exportNode node parentName) == false then
			return false

		for child in node.children do
			exportNodeRecursive child node.name
	)
	
	function exportMaterial mat =
	(
		format "\t{\n" vect to:ostream
		format "\t\tname: \"%\",\n" mat.name to:ostream
		col = mat.ambient
		format "\t\tambient: [%, %, %, %],\n" (col.red as integer) (col.green as integer) (col.blue as integer) (col.alpha as integer) to:ostream
		col = mat.diffuse
		format "\t\tdiffuse: [%, %, %, %],\n" (col.red as integer) (col.green as integer) (col.blue as integer) (col.alpha as integer) to:ostream
		col = mat.specular
		format "\t\tspecular: [%, %, %, %],\n" (col.red as integer) (col.green as integer) (col.blue as integer) (col.alpha as integer) to:ostream
		col = mat.selfIllumColor
		format "\t\temission: [%, %, %, %],\n" (col.red as integer) (col.green as integer) (col.blue as integer) (col.alpha as integer) to:ostream
		format "\t\tshininess: %,\n" mat.specularLevel to:ostream
		
		if mat.ambientMap != undefined then
			format "\t\ttexture: \"%\",\n" mat.ambientMap.filename to:ostream
		else if mat.diffuseMap != undefined then
			format "\t\ttexture: \"%\",\n" mat.diffuseMap.filename to:ostream
		
		format "\t},\n" vect to:ostream
	)
	
	function exportJSL =
	(
		format "// JavaScript Literal exported from 3ds Max 2010.\n" to:ostream
		format "// Exporter utility written by Asteroth 16/05/2010.\n" to:ostream
		format "\n" to:ostream
		format ("version: " + version + ",\n") to:ostream
		format ("date: \"" + localtime + "\",\n") to:ostream
		format "\n" to:ostream
		
		if cbExportMaterials.checked then
		(
			format "materials: [\n" to:ostream
			for mat in sceneMaterials do
				exportMaterial mat
			format "],\n\n" to:ostream
		)

		format "nodes: [\n" to:ostream
		if cbExportSelOnly.checked then
		(
			for node in selection do
				exportNode node ""
		)
		else
		(
			for node in rootnode.children do
				exportNodeRecursive node ""
		)
		format "],\n\n" to:ostream
	)

	on btnExport pressed do
	(
		fname = GetSaveFileName types:"JavaScript Literal (*.jsl)|*.jsl|All Files (*.*)|*.*|"
		if fname == undefined then
			return undefined

		ostream = CreateFile fname
		if ostream != undefined then
		(
			exportJSL()
			close ostream
		)
		else
		(
			MessageBox "Couldn't open file for writing!"
		)
	)

)